//
//  BlockViewController.m
//  Pthread
//
//  Created by Yanyan Jiang on 2020/12/6.
//  Copyright © 2020 Yanyan Jiang. All rights reserved.
//

#import "BlockViewController.h"
#import "BlockPerson.h"
#import "YYPersonTwo.h"
#import "YYRunTimePerson.h"

typedef void(^YYBlock)(void);

void blockRelease(void){
    YYPersonTwo *person = [[YYPersonTwo alloc] init];
    person.age = 10;
    YYPersonTwo *weakPerson = person;
    YYBlock block;
    block = ^{
        NSLog(@"------ %d",weakPerson.age);
    };
    block();
}


void block2(void){
    __block int age = 10;
    NSMutableArray *arr = [NSMutableArray array];
    YYBlock block = ^{
        //这样是不会报错的，因为不是在改arr的指针，只是在使用arr; 不像age那样修改age的值
        [arr addObject:@"123"];
        [arr addObject:@"456"];
        age = 20;
        NSLog(@"age is %d",age);
    };
    block();
}


void block3(void){
    //'__weak' only applies to Objective-C object or block pointer types; type here is 'int'
    __block int age = 10;
    NSObject *obj = [[NSObject alloc] init];
    __weak NSObject *weakObj = obj;
    YYBlock block = ^{
        age = 20;
        NSLog(@"age is %d",age);
        NSLog(@"%p",weakObj);
    };
    struct __main_block_impl_0 *blockImpl = (__bridge struct __main_block_impl_0 *)block;
    //(lldb) p/x blockImpl->age
    //(__Block_byref_age_0 *) $0 = 0x0000000100455540
    //(lldb) p/x blockImpl->age->age
    //(int) $1 = 0x0000000a
    //(lldb) p/x &(blockImpl->age->age)
    //(int *) $2 = 0x0000000100455558
    //2020-12-08 15:34:56.425931+0800 Block[41263:2837102] 0x100455558
    NSLog(@"%p",&age);

    //如果是__block 修改的变量是强引用；
    //__strong 是强引用 __weak 是弱引用
}

void block4(void){
    __block  YYPersonTwo *person = [[YYPersonTwo alloc] init];
    __weak YYPersonTwo *weakperson = person;
    person.block = ^{
        NSLog(@"%p",weakperson);
    };
    person.block();
}

void block5(void){
    //这种方式也能解决循环引用，但是要要调用block才能解决循环引用，如果没有机会执行这个block就会有内存泄漏
    __block  YYPersonTwo *person = [[YYPersonTwo alloc] init];
    person.block = ^{
        NSLog(@"%p",person);
        person = nil;
    };
    person.block();
}

void block6(void){
    //MRC环境下是不支持__weak的
    //__unsafe_unretained  YYPerson *person = [[YYPerson alloc] init];
    //MRC环境下block结构体中的person指针是不会对person进行强引用的
    __block  YYPersonTwo *person = [[YYPersonTwo alloc] init];
    person.block = [^{
        //NSLog(@"%p",person);
    } copy];
    
    //[person release];
    //person.block();
    NSLog(@"22222");
}

struct __block_impl {
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
};

struct __main_block_desc_0 {
    size_t reserved;
    size_t Block_size;
    void (*copy)(void);
    void (*dispose)(void);
};

struct __Block_byref_age_0 {
  void *__isa; //8
  struct __Block_byref_age_0 *__forwarding;//8
  int __flags;//4
  int __size;//4
  int age;
};


struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  struct __Block_byref_age_0 *age; // by ref
};


@interface BlockViewController (){
    void(^block)(void);
    int _age1;
    int _height1;
}
@end


@implementation BlockViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *test = @"8888";
    id cls = [BlockPerson class];
    void *obj = &cls;
    [(__bridge id)obj print];
}


//runtime方法测试
//消息发送、动态解析、消息转发
- (void)runTimeTest{
    YYRunTimePerson *rtPerson  = [[YYRunTimePerson alloc] init];
    //[rtPerson test];
    //[YYRunTimePerson testCls];
    //[rtPerson forwardingTest];
    //[rtPerson forwardingArgumentTest:10];
    [YYRunTimePerson testCls];
    
    //[rtPerson setAge:200];
    //rtPerson.age = 100;
    //NSLog(@"%d",rtPerson.age);
}


- (void)testPersonTow{
    static int age = 10;
    YYBlock block = ^{
        age = 20;
        NSLog(@"age  is %d",age);
    } ;
    
    block();
    NSLog(@"22222");
}


- (void)testTest{
    __block int age = 10;
    void(^blockTest)(void) = ^{
        age = 20;
        NSLog(@"age is %d",age);
    };
    blockTest();
    NSLog(@"age is is %d",age);
}


//看person什么时候会释放，我的理解是只要person的引用计数不为0，person就不会释放
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    BlockPerson *person = [[BlockPerson alloc] init];
    __weak  BlockPerson *weakPerson = person;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1-------%p",weakPerson);
        NSLog(@"1-------%@",[NSThread currentThread]);

        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-------%p",person);
        });
    });
    NSLog(@"%s",__FUNCTION__);

}



- (void)block1{
    //__NSGlobalBlock__:NSBlock:NSObject
    void(^block1)(void) = ^{
        NSLog(@"hello jack");
    };
    
    int age = 10;
    void(^block2)(void) = ^{
        NSLog(@"hello jack age is %d",age);
    };
    
    NSLog(@"%@\n%@\n%@",[block1 class],[block2 class],[^{
        NSLog(@"hello rose age is %d",age);
    } class]);
    
    //block();
    NSLog(@"%@",[block class]);
    NSLog(@"%@",[[block class] superclass]);
    NSLog(@"%@",[[[block class] superclass] superclass]);
    //[self test];
    //block();
}


- (void)test2{
    _age1 = 10;
    _height1 = 10;
    void(^block)(void) = ^{
        NSLog(@"_age1 is %d  _height1 is %d",self->_age1,self->_height1);
    };
    _age1 = 20;
    _height1 = 20;
    block();
}

- (void)test{
    //我们定义的局部变量默认会有一个auto 关键字修饰，这个关键字是可以省略的，局部变量定义出来就是auto,所以auto可以默认不写，这种auto是自动变量，自动变量是什么意思呢？就是离开它对应的大括号{}就会自动销毁
    auto int age = 10;
    static int  height = 10;
    NSObject *obj  = [[NSObject alloc] init];
    block = ^{
        NSLog(@"%p",obj);
        NSLog(@"hello, world age is %d  height is %d",age,height);
    };
    age = 20;
    height = 20;
}

@end
